﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Scheduler;
using  Agent.Messaging;
using System.IO.IsolatedStorage;
using System.IO;
using System.Diagnostics;
using System.Windows.Threading;

namespace App2AgentCommunicationTest
{
  public partial class MainPage : PhoneApplicationPage
  {
    string agentScheduleName = "my_agent";
    MessageSender messageSender = null;
    MessageReceiver messageRecevier = null;

    DispatcherTimer sendTimer;

    bool expectingToLoseConnection = false;

    // Constructor
    public MainPage()
    {
      InitializeComponent();
      DetailedLogger.LogFileName = "CLIENT_LOG_FILE.TXT";

      messageSender = new MessageSender("toAgent");
      messageSender.Start();
      messageRecevier = new MessageReceiver("toApp");
      messageRecevier.Start();
      messageRecevier.MessageReceived += new EventHandler<MessageReceivedEventArgs>(messageRecevier_MessageReceived);
      messageRecevier.SenderDisconnected += new EventHandler(messageRecevier_SenderDisconnected);
      messageRecevier.Failed += new EventHandler(messageRecevier_Failed);
      messageRecevier.Stopped += new EventHandler(messageRecevier_Stopped);
      sendTimer = new DispatcherTimer();
      sendTimer.Interval = TimeSpan.FromSeconds(0.5);
      int x = 0;
      sendTimer.Tick += delegate { messageSender.SendMessage("test msg " + x); x++; };
    }

    void messageRecevier_Stopped(object sender, EventArgs e)
    {
      Dispatcher.BeginInvoke(delegate
      {
        outputList.Items.Insert(0, "Receiver stopped; state is " + messageRecevier.CurrentState);
      });
    }

    void messageRecevier_Failed(object sender, EventArgs e)
    {
      Dispatcher.BeginInvoke(delegate
      {
        outputList.Items.Insert(0, "Receiver failed; state is " + messageRecevier.CurrentState);
      });
    }

    void messageRecevier_SenderDisconnected(object sender, EventArgs e)
    {
      if (expectingToLoseConnection != true)
      {
        Debug.WriteLine("Didn't get close message before agent shutdown...");
      }
      Dispatcher.BeginInvoke(delegate
      {
        outputList.Items.Insert(0,"Lost connection to agent");
        messageRecevier.Stop();
        messageRecevier.Start();
        RunAgentNow(null, new RoutedEventArgs());
      });
    }

    void messageRecevier_MessageReceived(object sender, MessageReceivedEventArgs e)
    {
      if (e.Message.Contains("Agent shutting down"))
        expectingToLoseConnection = true;
      else
        expectingToLoseConnection = false;

      Dispatcher.BeginInvoke(delegate
      {
        outputList.Items.Insert(0, "Received: " + e.Message);
      });
    }

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
      var schedule = ScheduledActionService.Find(agentScheduleName);
      UpdateUi(schedule != null);
    }

    private void UpdateUi(bool isAgentActive)
    {
      if (isAgentActive)
      {
        startAgentButton.IsEnabled = false;
        runAgentButton.IsEnabled = true;
        stopAgentButton.IsEnabled = true;
        sendTimer.Start();
      }
      else
      {
        startAgentButton.IsEnabled = true;
        runAgentButton.IsEnabled = false;
        stopAgentButton.IsEnabled = false;
        startAgentButton.Focus();
        sendTimer.Stop();
      }
    }

    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
    {
      if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
        DetailedLogger.Close();
    }

    private void StartAgent(object sender, RoutedEventArgs e)
    {
      PeriodicTask task = new PeriodicTask(agentScheduleName);
      task.Description = "Test task";
      task.ExpirationTime = DateTime.Now.AddDays(1);
      ScheduledActionService.Add(task);

      UpdateUi(true);
    }

    private void StopAgent(object sender, RoutedEventArgs e)
    {
      foreach (PeriodicTask task in ScheduledActionService.GetActions<PeriodicTask>())
        ScheduledActionService.Remove(task.Name);

      UpdateUi(false);
    }

    private void SendMessage(object sender, RoutedEventArgs e)
    {
      messageSender.SendMessage(messageText.Text);
      messageText.Focus();
    }

    private void ClearList(object sender, RoutedEventArgs e)
    {
      outputList.Items.Clear();
      DetailedLogger.DeleteLogFile();
      // TODO: support actual metadata with messages rather than just strings
      messageSender.SendMessage("$$DELETE_LOG$$");
    }

    private void DumpAgentLog(object sender, RoutedEventArgs e)
    {
      DumpAllLogs();
    }

    private static void DumpAllLogs()
    {
      var isf = IsolatedStorageFile.GetUserStoreForApplication();
      DumpLogFile(isf, "CLIENT_LOG_FILE.TXT");
      DumpLogFile(isf, "AGENT_LOG_FILE.TXT");
    }

    private static void DumpLogFile(IsolatedStorageFile isf, string fileName)
    {
      if (isf.FileExists(fileName) != true)
        return;

      var stream = isf.OpenFile(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
      var reader = new StreamReader(stream);
      string line = null;

      Debugger.Break();
      // Clear the output window and then continue...

      while ((line = reader.ReadLine()) != null)
        Debug.WriteLine(line);

      // Now copy the output window to notepad
      Debugger.Break();
    }

    private void RunAgentNow(object sender, RoutedEventArgs e)
    {
      ScheduledActionService.LaunchForTest(agentScheduleName, TimeSpan.Zero);
    }
  }
}